﻿using NHibernate;
using com.pro2e.console.core.hibernate;
using com.pro2e.console.generic.staledata;
using System.Collections;
using System;
using System.Collections.Generic;
using com.pro2e.console.service.msg.vo;
using NHibernate.Criterion;
using com.pro2e.web.log;

/// <summary>
/// DaoImp 的摘要描述
/// </summary>
/// 
namespace com.pro2e.console.core.valueobject
{
    public class DaoImp : IDao
    {
        log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        VersionService versionService = new VersionService();
        WebLogService webLogService = new WebLogService();

        #region IDao 成員

        public ISession GetHBNSession()
        {
            ISession session = NHibernateSessionManager.Instance.GetSession();
            return (session);

        }

       

        public void DaoUpdate(Object o)
        {
            log.Debug("DaoUpdate");
            webLogService.AddSystemLog(MsgVO.Action.修改, o);
            GetHBNSession().Update(o);
        }

        public void DaoInsert(Object o)
        {
            log.Debug("DaoInsert");
            webLogService.AddSystemLog(MsgVO.Action.新增, o);
            GetHBNSession().Save(o);
            
        }
        
        public void DaoSaveOrUpdate(Object o)
        {
            log.Debug("DaoSaveOrUpdate");
            webLogService.AddSystemLog(MsgVO.Action.新增或修改, o);
            GetHBNSession().SaveOrUpdate(o);
        }
        public void DaoSaveOrUpdateCopy(Object o)
        {
            log.Debug("DaoSaveOrUpdateCopy");
            webLogService.AddSystemLog(MsgVO.Action.新增或修改, o);
            GetHBNSession().SaveOrUpdateCopy(o);
        }
        public void DaoDelete(Object o)
        {
            log.Debug("DaoDelete");
            webLogService.AddSystemLog(MsgVO.Action.刪除, o);
            GetHBNSession().Delete(o);
        }
        public void DaoQueryLog(Object o)
        {
            log.Debug("DaoQueryLog");
            webLogService.AddSystemLog(MsgVO.Action.查詢, o);
        }


        public T DaoGetVOById<T>(object keyId)
        {
            T result = GetHBNSession().Get<T>(keyId);

            if (result != null)
            {
                return result;
            }
            else
            {
                return default(T);
            }


        }

        public T DaoGetTmpVOById<T>(object keyId)
        {

            T result = GetHBNSession().Get<T>(keyId);

            if (result != null)
            {
                GetHBNSession().Evict(result);
                return result;
            }
            else
            {
                return default(T);
            }
        }

        /// <summary>
        /// 取得全部的VO
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IList<T> DaoGetAllVO<T>()
        {
            IQuery query = GetHBNSession().CreateQuery(string.Format("From {0} ", typeof(T).Name));

            if (query.List() != null)
            {
                return (query.List<T>());
            }
            else
            {
                return null;
            }

        }


        /// <summary>
        /// 執行預先定義好的DetachedCriteria
        /// </summary>
        /// <typeparam name="T">轉型型別</typeparam>
        /// <param name="detachedcriteria">預先準備好的條件</param>
        /// <param name="firstRow">第一筆的位置</param>
        /// <param name="MaxRecord">取最多幾筆</param>
        /// <returns></returns>
        public IList<T> ExecutableDetachedCriteria<T>(DetachedCriteria detachedcriteria, int firstRow, int MaxRecord)
        {
            ICriteria criteria = detachedcriteria.GetExecutableCriteria(GetHBNSession());
            criteria.SetFirstResult(firstRow);
            criteria.SetMaxResults(MaxRecord);
            return (criteria.List<T>());
        }

        /// <summary>
        /// 執行預先定義好的DetachedCriteria並傳回一筆資料
        /// </summary>
        /// <typeparam name="T">轉型型別</typeparam>
        /// <param name="detachedcriteria">預先準備好的條件</param>
        /// <param name="firstRow">第一筆的位置</param>
        /// <param name="MaxRecord">取最多幾筆</param>
        /// <returns></returns>
        public T ExecutableDetachedCriteriaUnique<T>(DetachedCriteria detachedcriteria)
        {
            ICriteria criteria = detachedcriteria.GetExecutableCriteria(GetHBNSession());
            criteria.SetMaxResults(1);
            return (criteria.UniqueResult<T>());
        }

        /// <summary>
        /// 執行預先定義好的DetachedCriteria
        /// </summary>
        /// <typeparam name="T">轉型型別</typeparam>
        /// <returns></returns>
        public IList<T> ExecutableDetachedCriteria<T>(DetachedCriteria detachedcriteria)
        {
            ICriteria criteria = detachedcriteria.GetExecutableCriteria(GetHBNSession());
            return (criteria.List<T>());
        }

        /// <summary>
        /// 執行預先定義好的DetachedCriteria
        /// </summary>
        /// <typeparam name="T">轉型型別</typeparam>
        /// <returns></returns>
        public T ExecutableDetachedCriteria<T>(DetachedCriteria detachedcriteria, bool isUnique)
        {

            ICriteria criteria = detachedcriteria.GetExecutableCriteria(GetHBNSession());
            return (criteria.UniqueResult<T>());
        }

        /// <summary>
        /// 計算總筆數
        /// </summary>
        /// <returns></returns>
        public int CountDetachedCriteriaRow(DetachedCriteria detachedcriteria)
        {
            DetachedCriteria tmpCriteria = CriteriaTransformer.Clone(detachedcriteria);
            tmpCriteria.Orders.Clear();

            ICriteria criteria = tmpCriteria.GetExecutableCriteria(GetHBNSession());

            ProjectionList projection = Projections.ProjectionList();
            projection.Add(Projections.RowCount());
            return (int)criteria.SetProjection(projection).UniqueResult();
        }

        /// <summary>
        /// 計算總筆數
        /// </summary>
        /// <typeparam name="T">傳回的物件</typeparam>
        /// <returns>筆數</returns>
        public int DaoTotalRecordCount<T>()
        {
            ICriteria criteria = GetHBNSession().CreateCriteria(typeof(T));
            return ((int)criteria.SetProjection((Projections.ProjectionList().Add(Projections.RowCount()))).UniqueResult());
        }

        /// <summary>
        /// 取出VO全部 by 分頁
        /// </summary>
        /// <typeparam name="T">類型</typeparam>
        /// <param name="firstRow">從那筆位置開始</param>
        /// <param name="MaxRecord">一頁幾筆</param>
        /// <returns></returns>
        public IList<T> DaoGetAllVOByPage<T>(int firstRow, int MaxRecord)
        {
            ICriteria criteria = GetHBNSession().CreateCriteria(typeof(T));
            criteria.SetFirstResult(firstRow);
            criteria.SetMaxResults(MaxRecord);
            return (criteria.List<T>());
        }

        #endregion

        /// <summary>
        /// 檢查是否版本相同
        /// </summary>
        /// <param name="o">檢查的物件</param>
        /// <param name="key">key值</param>
        protected void CheckVersion(object o, object key)
        {
            versionService.CheckVersion(o, key);
        }

        /// <summary>
        /// 動態查詢
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public IList<T> DaoGetByWhere<T>(string where)
        {
            //使用反射
            T obj = (T)System.Reflection.Assembly.GetAssembly(typeof(T)).CreateInstance(typeof(T).ToString());

            string hql = string.Format("from {0} {1}",
                obj.GetType().ToString(),
                where.ToUpper().IndexOf("WHERE") != -1 ? where : "WHERE " + where);

            log.Debug("hql:" + hql);
            IQuery query = GetHBNSession().CreateQuery(hql);

            IList<T> list = query.List<T>();
            return list;
        }

        /// <summary>
        /// 動態查詢並分頁結果
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <param name="starIndex">首筆位置</param>
        /// <param name="maxRecord">最大筆數</param>
        /// <returns></returns>
        public IList<T> DaoGetByWhere<T>(string where, int starIndex, int maxRecord)
        {
            //使用反射
            T obj = (T)System.Reflection.Assembly.GetAssembly(typeof(T)).CreateInstance(typeof(T).ToString());

            string hql = string.Format("from {0} {1}",
                obj.GetType().ToString(),
                where.ToUpper().IndexOf("WHERE") != -1 ? where : "WHERE " + where);


            log.Debug("hql:" + hql);
            IQuery query = GetHBNSession().CreateQuery(hql);
            query.SetFirstResult(starIndex);
            query.SetMaxResults(maxRecord);
            IList<T> list = query.List<T>();
            return list;
        }


        /// <summary>
        /// 取出VO全部 by 分頁
        /// </summary>
        /// <typeparam name="T">類型</typeparam>
        /// <param name="firstRow">從那筆位置開始</param>
        /// <param name="MaxRecord">一頁幾筆</param>
        /// <param name="order">SortOrder</param>
        /// <returns></returns>
        public IList<T> DaoGetAllVOByPage<T>(int firstRow, int MaxRecord, Order order)
        {
            ICriteria criteria = GetHBNSession().CreateCriteria(typeof(T));
            criteria.SetFirstResult(firstRow);
            criteria.SetMaxResults(MaxRecord);
            criteria.AddOrder(order);
            return (criteria.List<T>());
        }

        /// <summary>
        /// 動態查詢筆數
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public int DaoCountByWhere<T>(string where)
        {
            //使用反射
            T obj = (T)System.Reflection.Assembly.GetAssembly(typeof(T)).CreateInstance(typeof(T).ToString());

            string hql = string.Format("from {0} {1}",
                obj.GetType().ToString(),
                where.ToUpper().IndexOf("WHERE") != -1 ? where : "WHERE " + where);

            hql = string.Format("select count(*) {0}", hql);

            log.Debug("hql:" + hql);
            IQuery query = GetHBNSession().CreateQuery(hql);

            return (int.Parse(query.UniqueResult().ToString()));
        }
    }
}